home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / Java2 / src / java / security / MessageDigest.java < prev    next >
Encoding:
Java Source  |  1999-05-28  |  14.7 KB  |  474 lines  |  [TEXT/CWIE]

  1. /*
  2.  * @(#)MessageDigest.java    1.62 98/07/17
  3.  *
  4.  * Copyright 1996-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.security;
  16.  
  17. import java.util.*;
  18. import java.lang.*;
  19. import java.io.IOException;
  20. import java.io.ByteArrayOutputStream;
  21. import java.io.PrintStream;
  22. import java.io.InputStream;
  23. import java.io.ByteArrayInputStream;
  24.  
  25. /**
  26.  * This MessageDigest class provides applications the functionality of a
  27.  * message digest algorithm, such as MD5 or SHA.
  28.  * Message digests are secure one-way hash functions that take arbitrary-sized
  29.  * data and output a fixed-length hash value.
  30.  *
  31.  * <p>A MessageDigest object starts out initialized. The data is 
  32.  * processed through it using the {@link update(byte) update}
  33.  * methods. At any point {@link reset() reset} can be called
  34.  * to reset the digest. Once all the data to be updated has been
  35.  * updated, one of the {@link digest() digest} methods should 
  36.  * be called to complete the hash computation.
  37.  *
  38.  * <p>The <code>digest</code> method can be called once for a given number 
  39.  * of updates. After <code>digest</code> has been called, the MessageDigest
  40.  * object is reset to its initialized state.
  41.  *
  42.  * <p>Implementations are free to implement the Cloneable interface.
  43.  * Client applications can test cloneability by attempting cloning
  44.  * and catching the CloneNotSupportedException: <p>    
  45.  *
  46. * <pre>
  47. * MessageDigest md = MessageDigest.getInstance("SHA");
  48. *
  49. * try {
  50. *     md.update(toChapter1);
  51. *     MessageDigest tc1 = md.clone();
  52. *     byte[] toChapter1Digest = tc1.digest;
  53. *     md.update(toChapter2);
  54. *     ...etc.
  55. * } catch (CloneNotSupportedException cnse) {
  56. *     throw new DigestException("couldn't make digest of partial content");
  57. * }
  58. * </pre>
  59.  *
  60.  * <p>Note that if a given implementation is not cloneable, it is
  61.  * still possible to compute intermediate digests by instantiating
  62.  * several instances, if the number of digests is known in advance.
  63.  *
  64.  * <p>Note that this class is abstract and extends from
  65.  * <code>MessageDigestSpi</code> for historical reasons.
  66.  * Application developers should only take notice of the methods defined in
  67.  * this <code>MessageDigest</code> class; all the methods in
  68.  * the superclass are intended for cryptographic service providers who wish to
  69.  * supply their own implementations of message digest algorithms.
  70.  *
  71.  * @author Benjamin Renaud 
  72.  *
  73.  * @version 1.62 99/03/26
  74.  *
  75.  * @see DigestInputStream
  76.  * @see DigestOutputStream
  77.  */
  78.  
  79. public abstract class MessageDigest extends MessageDigestSpi {
  80.  
  81.     private String algorithm;
  82.  
  83.     // The state of this digest
  84.     private static final int INITIAL = 0;
  85.     private static final int IN_PROGRESS = 1;
  86.     private int state = INITIAL;
  87.  
  88.     // The provider
  89.     private Provider provider;
  90.  
  91.     /**
  92.      * Creates a message digest with the specified algorithm name.
  93.      * 
  94.      * @param algorithm the standard name of the digest algorithm. 
  95.      * See Appendix A in the <a href=
  96.      * "../../../guide/security/CryptoSpec.html#AppA">
  97.      * Java Cryptography Architecture API Specification & Reference </a> 
  98.      * for information about standard algorithm names.
  99.      */
  100.     protected MessageDigest(String algorithm) {
  101.     this.algorithm = algorithm;
  102.     }
  103.  
  104.     /**
  105.      * Generates a MessageDigest object that implements the specified digest
  106.      * algorithm. If the default provider package
  107.      * provides an implementation of the requested digest algorithm,
  108.      * an instance of MessageDigest containing that implementation is returned.
  109.      * If the algorithm is not available in the default 
  110.      * package, other packages are searched.
  111.      *
  112.      * @param algorithm the name of the algorithm requested. 
  113.      * See Appendix A in the <a href=
  114.      * "../../../guide/security/CryptoSpec.html#AppA">
  115.      * Java Cryptography Architecture API Specification & Reference </a> 
  116.      * for information about standard algorithm names.
  117.      *
  118.      * @return a Message Digest object implementing the specified
  119.      * algorithm.
  120.      *
  121.      * @exception NoSuchAlgorithmException if the algorithm is
  122.      * not available in the caller's environment.  
  123.      */
  124.     public static MessageDigest getInstance(String algorithm) 
  125.     throws NoSuchAlgorithmException { 
  126.     try {
  127.         Object[] objs = Security.getImpl(algorithm, "MessageDigest", null);
  128.         if (objs[0] instanceof MessageDigest) {
  129.         MessageDigest md = (MessageDigest)objs[0];
  130.         md.provider = (Provider)objs[1];
  131.         return md;
  132.         } else {
  133.         MessageDigest delegate =
  134.             new Delegate((MessageDigestSpi)objs[0], algorithm);
  135.         delegate.provider = (Provider)objs[1];
  136.         return delegate;
  137.         }
  138.     } catch(NoSuchProviderException e) {
  139.         throw new NoSuchAlgorithmException(algorithm + " not found");
  140.     }
  141.     }
  142.  
  143.     /**
  144.      * Generates a MessageDigest object implementing the specified
  145.      * algorithm, as supplied from the specified provider, if such an 
  146.      * algorithm is available from the provider.
  147.      *
  148.      * @param algorithm the name of the algorithm requested. 
  149.      * See Appendix A in the <a href=
  150.      * "../../../guide/security/CryptoSpec.html#AppA">
  151.      * Java Cryptography Architecture API Specification & Reference </a> 
  152.      * for information about standard algorithm names.
  153.      *
  154.      * @param provider the name of the provider.
  155.      *
  156.      * @return a Message Digest object implementing the specified
  157.      * algorithm.
  158.      *
  159.      * @exception NoSuchAlgorithmException if the algorithm is
  160.      * not available in the package supplied by the requested
  161.      * provider.
  162.      *
  163.      * @exception NoSuchProviderException if the provider is not
  164.      * available in the environment. 
  165.      * 
  166.      * @see Provider 
  167.      */
  168.     public static MessageDigest getInstance(String algorithm, String provider)
  169.     throws NoSuchAlgorithmException, NoSuchProviderException
  170.     {
  171.     if (provider == null || provider.length() == 0)
  172.         throw new IllegalArgumentException("missing provider");
  173.     Object[] objs = Security.getImpl(algorithm, "MessageDigest", provider);
  174.     if (objs[0] instanceof MessageDigest) {
  175.         MessageDigest md = (MessageDigest)objs[0];
  176.         md.provider = (Provider)objs[1];
  177.         return md;
  178.     } else {
  179.         MessageDigest delegate =
  180.         new Delegate((MessageDigestSpi)objs[0], algorithm);
  181.         delegate.provider = (Provider)objs[1];
  182.         return delegate;
  183.     }
  184.     }
  185.  
  186.     /** 
  187.      * Returns the provider of this message digest object.
  188.      * 
  189.      * @return the provider of this message digest object
  190.      */
  191.     public final Provider getProvider() {
  192.     return this.provider;
  193.     }
  194.  
  195.     /**
  196.      * Updates the digest using the specified byte.    
  197.      * 
  198.      * @param input the byte with which to update the digest.
  199.      */
  200.     public void update(byte input) {
  201.     engineUpdate(input);
  202.     state = IN_PROGRESS;
  203.     }
  204.  
  205.     /**
  206.      * Updates the digest using the specified array of bytes, starting
  207.      * at the specified offset.
  208.      * 
  209.      * @param input the array of bytes.
  210.      *
  211.      * @param offset the offset to start from in the array of bytes.
  212.      *
  213.      * @param len the number of bytes to use, starting at 
  214.      * <code>offset</code>.  
  215.      */
  216.     public void update(byte[] input, int offset, int len) {
  217.     if (input == null) {
  218.         throw new IllegalArgumentException("No input buffer given");
  219.     }
  220.     if (input.length - offset < len) {
  221.         throw new IllegalArgumentException("Input buffer too short");
  222.     }
  223.     engineUpdate(input, offset, len);
  224.     state = IN_PROGRESS;
  225.     }
  226.  
  227.     /**
  228.      * Updates the digest using the specified array of bytes.
  229.      * 
  230.      * @param input the array of bytes.
  231.      */
  232.     public void update(byte[] input) {
  233.     engineUpdate(input, 0, input.length);
  234.     state = IN_PROGRESS;
  235.     }
  236.  
  237.     /**
  238.      * Completes the hash computation by performing final operations
  239.      * such as padding. The digest is reset after this call is made.
  240.      *
  241.      * @return the array of bytes for the resulting hash value.  
  242.      */
  243.     public byte[] digest() {
  244.     /* Resetting is the responsibility of implementors. */
  245.     byte[] result = engineDigest();
  246.     state = INITIAL;
  247.     return result;
  248.     }
  249.  
  250.     /**
  251.      * Completes the hash computation by performing final operations
  252.      * such as padding. The digest is reset after this call is made.
  253.      *
  254.      * @param buf output buffer for the computed digest
  255.      *
  256.      * @param offset offset into the output buffer to begin storing the digest
  257.      *
  258.      * @param len number of bytes within buf allotted for the digest
  259.      *
  260.      * @return the number of bytes placed into <code>buf</code>
  261.      * 
  262.      * @exception DigestException if an error occurs.
  263.      */
  264.     public int digest(byte[] buf, int offset, int len) throws DigestException {
  265.     if (buf == null) {
  266.         throw new IllegalArgumentException("No output buffer given");
  267.     }
  268.     if (buf.length - offset < len) {
  269.         throw new IllegalArgumentException
  270.         ("Output buffer too small for specified offset and length");
  271.     }
  272.     int numBytes = engineDigest(buf, offset, len);
  273.     state = INITIAL;
  274.     return numBytes;
  275.     }
  276.  
  277.     /**
  278.      * Performs a final update on the digest using the specified array 
  279.      * of bytes, then completes the digest computation. That is, this
  280.      * method first calls <a href = "#update(byte[])">update(input)</a>,
  281.      * passing the <i>input</i> array to the <code>update</code> method,
  282.      * then calls {@link digest() digest()}.
  283.      *
  284.      * @param input the input to be updated before the digest is
  285.      * completed.
  286.      *
  287.      * @return the array of bytes for the resulting hash value.  
  288.      */
  289.     public byte[] digest(byte[] input) {
  290.     update(input);
  291.     return digest();
  292.     }
  293.  
  294.     /**
  295.      * Returns a string representation of this message digest object.  
  296.      */
  297.     public String toString() {
  298.     ByteArrayOutputStream baos = new ByteArrayOutputStream();
  299.     PrintStream p = new PrintStream(baos);
  300.     p.print(algorithm+" Message Digest from "+provider.getName()+", ");
  301.     switch (state) {
  302.     case INITIAL:
  303.         p.print("<initialized>");
  304.         break;
  305.     case IN_PROGRESS:
  306.         p.print("<in progress>");
  307.         break;
  308.     }
  309.     p.println();
  310.     return (baos.toString());
  311.     }
  312.  
  313.     /**
  314.      * Compares two digests for equality. Does a simple byte compare.
  315.      * 
  316.      * @param digesta one of the digests to compare.
  317.      * 
  318.      * @param digestb the other digest to compare.    
  319.      *
  320.      * @return true if the digests are equal, false otherwise.
  321.      */
  322.     public static boolean isEqual(byte digesta[], byte digestb[]) {
  323.     if (digesta.length != digestb.length)
  324.         return false;
  325.  
  326.     for (int i = 0; i < digesta.length; i++) {
  327.         if (digesta[i] != digestb[i]) {
  328.         return false;
  329.         }
  330.     }
  331.     return true;
  332.     }
  333.  
  334.     /**
  335.      * Resets the digest for further use.
  336.      */
  337.     public void reset() {
  338.     engineReset();
  339.     state = INITIAL;
  340.     }
  341.  
  342.     /** 
  343.      * Returns a string that identifies the algorithm, independent of
  344.      * implementation details. The name should be a standard
  345.      * Java Security name (such as "SHA", "MD5", and so on). 
  346.      * See Appendix A in the <a href=
  347.      * "../../../guide/security/CryptoSpec.html#AppA">
  348.      * Java Cryptography Architecture API Specification & Reference </a> 
  349.      * for information about standard algorithm names.
  350.      */
  351.     public final String getAlgorithm() {
  352.     return this.algorithm;
  353.     }
  354.  
  355.     /** 
  356.      * Returns the length of the digest in bytes, or 0 if this operation is
  357.      * not supported by the provider and the implementation is not cloneable.
  358.      *
  359.      * @return the digest length in bytes, or 0 if this operation is not
  360.      * supported by the provider and the implementation is not cloneable.
  361.      * 
  362.      * @since JDK1.2
  363.      */
  364.     public final int getDigestLength() {
  365.     int digestLen = engineGetDigestLength();
  366.     if (digestLen == 0) {
  367.         try {
  368.         MessageDigest md = (MessageDigest)clone();
  369.         byte[] digest = md.digest();
  370.         return digest.length;
  371.         } catch (CloneNotSupportedException e) {
  372.         return digestLen;
  373.         }
  374.     }
  375.     return digestLen;
  376.     }
  377.  
  378.     /**    
  379.      * Returns a clone if the implementation is cloneable.    
  380.      * 
  381.      * @return a clone if the implementation is cloneable.
  382.      *
  383.      * @exception CloneNotSupportedException if this is called on an
  384.      * implementation that does not support <code>Cloneable</code>.
  385.      */
  386.     public Object clone() throws CloneNotSupportedException {
  387.     if (this instanceof Cloneable) {
  388.         return super.clone();
  389.     } else {
  390.         throw new CloneNotSupportedException();
  391.     }
  392.     }
  393.  
  394.  
  395.  
  396.  
  397.     /*
  398.      * The following class allows providers to extend from MessageDigestSpi
  399.      * rather than from MessageDigest. It represents a MessageDigest with an
  400.      * encapsulated, provider-supplied SPI object (of type MessageDigestSpi).
  401.      * If the provider implementation is an instance of MessageDigestSpi,
  402.      * the getInstance() methods above return an instance of this class, with
  403.      * the SPI object encapsulated.
  404.      *
  405.      * Note: All SPI methods from the original MessageDigest class have been
  406.      * moved up the hierarchy into a new class (MessageDigestSpi), which has
  407.      * been interposed in the hierarchy between the API (MessageDigest)
  408.      * and its original parent (Object).
  409.      */
  410.  
  411.     static class Delegate extends MessageDigest {
  412.  
  413.     // The provider implementation (delegate)
  414.     private MessageDigestSpi digestSpi;
  415.  
  416.     // constructor
  417.     public Delegate(MessageDigestSpi digestSpi, String algorithm) {
  418.         super(algorithm);
  419.         this.digestSpi = digestSpi;
  420.     }
  421.  
  422.     /*
  423.      * Returns a clone if the delegate is cloneable.    
  424.      * 
  425.      * @return a clone if the delegate is cloneable.
  426.      *
  427.      * @exception CloneNotSupportedException if this is called on a
  428.      * delegate that does not support <code>Cloneable</code>.
  429.      */
  430.     public Object clone() throws CloneNotSupportedException {
  431.         if (digestSpi instanceof Cloneable) {
  432.         MessageDigestSpi digestSpiClone =
  433.             (MessageDigestSpi)digestSpi.clone();    
  434.         // Because 'algorithm', 'provider', and 'state' are private
  435.         // members of our supertype, we must perform a cast to
  436.         // access them.
  437.         MessageDigest that =
  438.             new Delegate(digestSpiClone,
  439.                  ((MessageDigest)this).algorithm);
  440.         that.provider = ((MessageDigest)this).provider;
  441.         that.state = ((MessageDigest)this).state;
  442.         return that;
  443.         } else {
  444.         throw new CloneNotSupportedException();
  445.         }
  446.     }
  447.  
  448.     protected int engineGetDigestLength() {
  449.         return digestSpi.engineGetDigestLength();
  450.     }
  451.  
  452.     protected void engineUpdate(byte input) {
  453.         digestSpi.engineUpdate(input);
  454.     }
  455.  
  456.     protected void engineUpdate(byte[] input, int offset, int len) {
  457.         digestSpi.engineUpdate(input, offset, len);
  458.     }
  459.  
  460.     protected byte[] engineDigest() {
  461.         return digestSpi.engineDigest();
  462.     }
  463.  
  464.     protected int engineDigest(byte[] buf, int offset, int len)
  465.         throws DigestException {
  466.         return digestSpi.engineDigest(buf, offset, len);
  467.     }
  468.  
  469.     protected void engineReset() {
  470.         digestSpi.engineReset();
  471.     }
  472.     }
  473. }
  474.